
#include "./wiimote.h"

#ifdef _PLATFORM_WIN32
#include "wiimote_win32.h"
#endif //_PLATFORM_WIN32
#ifdef _PLATFORM_WII
#include "wiimote_wii.h"
#endif //_PLATFORM_WII

#include "util/timer.h"				// log
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

#include <cassert>
using namespace input;

Wiimote& Wiimote::Instance()
{
	static Wiimote	Inst;
	return Inst;
};
Wiimote::Wiimote()
{
	m_Ctrl = NULL;

	for (unsigned int j=0; j<MAX_WIIMOTE; j++)
	{
		m_ControllerA[j].AccX = m_ControllerA[j].AccY = m_ControllerA[j].AccZ = 0.0f;
		m_ControllerA[j].RumbleTime = -1;
		for (unsigned int i=0; i<BUTTON_C; i++)
		{
			m_ControllerA[j].ButtonA[i].ClickTime = 0.0f;
			m_ControllerA[j].ButtonA[i].ID = (BUTTON_ID)i;
			m_ControllerA[j].ButtonA[i].IsChanged = false;
			m_ControllerA[j].ButtonA[i].IsDown = false;
		}
	}
	Init();
}
Wiimote::~Wiimote()
{
	Shutdown();
}
void	Wiimote::Tick(float dt)
{
	if (m_Ctrl) m_Ctrl->Tick(dt);
	for (unsigned int j=0; j<MAX_WIIMOTE; j++)
	{
		if (m_ControllerA[j].RumbleTime > 0)
		{
			m_ControllerA[j].RumbleTime -=dt;
			if (m_ControllerA[j].RumbleTime <= 0)
				StopRumble(j);
		}

	}
}

bool	Wiimote::IsDown(int	ControllerID, BUTTON_ID ID)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return false;
	assert(ID < BUTTON_C);
	return m_ControllerA[ControllerID].ButtonA[ID].IsDown;
}
bool	Wiimote::IsPressed(int	ControllerID, BUTTON_ID ID)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return false;
	assert(ID < BUTTON_C);
	return m_ControllerA[ControllerID].ButtonA[ID].IsDown &&  m_ControllerA[ControllerID].ButtonA[ID].IsChanged;
}
bool	Wiimote::IsReleased(int	ControllerID,BUTTON_ID ID)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return false;
	assert(ID < BUTTON_C);
	return (! m_ControllerA[ControllerID].ButtonA[ID].IsDown) &&  m_ControllerA[ControllerID].ButtonA[ID].IsChanged;
}

void	Wiimote::GetAcceleration(int	ControllerID, float& x, float& y, float& z)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return;
	x = m_ControllerA[ControllerID].AccX;
	y = m_ControllerA[ControllerID].AccY;
	z = m_ControllerA[ControllerID].AccZ;
}

void	Wiimote::AccelerationUpdate(int	ControllerID, float x, float y, float z)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return;
	Controller * pCtrl = &m_ControllerA[ControllerID];
	pCtrl->AccX = x;
	pCtrl->AccY = y;
	pCtrl->AccZ = z;
	for (unsigned int i=0; i<m_Listeners.size(); i++)
	{
		m_Listeners[i]->WiiAcceleration(ControllerID, x, y, z);
	}
}

void	Wiimote::ButtonUpdate(int	ControllerID, BUTTON_ID ID, bool IsDown)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return;
	if (ID >=BUTTON_C) return;
	Controller * pCtrl = &m_ControllerA[ControllerID];
	pCtrl->ButtonA[ID].IsChanged = (IsDown !=pCtrl->ButtonA[ID].IsDown);	// changed?
	pCtrl->ButtonA[ID].IsDown = IsDown;

	// edge
	if (pCtrl->ButtonA[ID].IsChanged)
	{
		if (IsDown)
		{
			pCtrl->ButtonA[ID].ClickTime = TIMER().Time();
			for (unsigned int i=0; i<m_Listeners.size(); i++)
			{
				m_Listeners[i]->WiiButtonPressed(ControllerID, &pCtrl->ButtonA[ID]);
			}
		} else
		{
			for (unsigned int i=0; i<m_Listeners.size(); i++)
			{
				m_Listeners[i]->WiiButtonReleased(ControllerID, &pCtrl->ButtonA[ID]);
			}
		}
	}
	// only do this on non-edge events?
	if (IsDown)
	{
		for (unsigned int i=0; i<m_Listeners.size(); i++)
		{
			m_Listeners[i]->WiiButtonDown(ControllerID, &pCtrl->ButtonA[ID]);
		}
	}
}

void	Wiimote::StartRumble(int ControllerID, float Time)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return;
	if (m_ControllerA[ControllerID].RumbleTime < 0)
	{
		if (m_Ctrl)	m_Ctrl->StartRumble(ControllerID);
	}
	m_ControllerA[ControllerID].RumbleTime = Time;

}

void	Wiimote::StopRumble(int ControllerID)
{
	if (ControllerID < 0 || ControllerID >= MAX_WIIMOTE) return;
	if (m_ControllerA[ControllerID].RumbleTime < 0)
	{
		if (m_Ctrl)	m_Ctrl->StopRumble(ControllerID);
	}
	m_ControllerA[ControllerID].RumbleTime = -1;

}


void	Wiimote::Init()
{
#if defined(_ENABLE_WIIMOTE)
	#if defined(_PLATFORM_WIN32)
		m_Ctrl = new WiimoteWin32();
	#endif
	#if defined(_PLATFORM_WII)
		m_Ctrl = new WiimoteWii();
	#endif

	if (m_Ctrl) m_Ctrl->Init();
#endif //_ENABLE_WIIMOTE
}
void	Wiimote::Shutdown()
{
	UTIL_SAFE_DELETE(m_Ctrl);
}


WiimoteListener::WiimoteListener() :
	m_IsEnabled(true)
{
	GET_WIIMOTE().AddListener(this);
}

WiimoteListener::~WiimoteListener()
{
	GET_WIIMOTE().DropListener(this);
}